/*************************************************************
*
* cgm_phys.cpp
*  phisics misc functions
*************************************************************/
#include <m3d/m3d_stdafx.h>

#include <math.h>
#include <stdio.h>
#include <stdlib.h>

#include <ap_comm.h>

#include <m3d.h>
#include <cgm.h>


//
// Static functions
//

//
// Static variables
//


/*************************************************************
* cgmGetThrowSpeed_XZ ()
*
*************************************************************/
float cgmGetThrowSpeed_XZ (m3dV *orgThrow, m3dV *orgTarget, float speedXZ, float accelY, m3dV *iniSpeed)
{
   m3dV     dir;
   float    t, speedY;

   m3dSubtractVector(orgTarget, orgThrow, &dir);
   dir.y = 0.f;
   m3dNormalize(&dir);

   _m3dScaleVector(&dir, speedXZ);

   t = m3xzDist(orgThrow, orgTarget) / speedXZ;

   speedY = (orgTarget->y - orgThrow->y - accelY*t*t/2.f)/t;

   *iniSpeed   = dir;
   iniSpeed->y = speedY;

   return t;
}
/*************************************************************
* cgmGetThrowSpeed_H ()
*
*************************************************************/
float cgmGetThrowSpeed_H (m3dV *orgThrow, m3dV *orgTarget, float maxHeight, float accelY, m3dV *iniSpeed)
{
   float    speedY;

   speedY = m3dSqrt(2.f * m3dFAbs(accelY) * maxHeight);
   return cgmGetThrowSpeed_Y(orgThrow, orgTarget, speedY, accelY, iniSpeed);
}
/*************************************************************
* cgmGetThrowSpeed_Y ()
*
*************************************************************/
float cgmGetThrowSpeed_Y (m3dV *orgThrow, m3dV *orgTarget, float speedY, float accelY, m3dV *iniSpeed)
{
   m3dV     dir;
   float    t, t1, t2, speedXZ;

   if (m3dSolveQuadraticEq(accelY / 2.f, speedY, orgThrow->y - orgTarget->y, &t1, &t2) == 0) {
      ASSERT(FALSE);
      t       = 0.f;
      speedXZ = 0.f;
   } else {
      t       = max(t1, t2);
      speedXZ = m3xzDist(orgTarget, orgThrow) / t;
   }

   m3dSubtractVector(orgTarget, orgThrow, &dir);
   dir.y = 0.f;
   m3dNormalize(&dir);

   _m3dScaleVector(&dir, speedXZ);

   *iniSpeed   = dir;
   iniSpeed->y = speedY;

   return t;
}

//
// end of file "cgm_phys.cpp"
//
